package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"
	"todolist/auth"
	"todolist/config"

	_ "github.com/go-sql-driver/mysql"
)

// 定义返回的分页数据结构
type PaginatedResponse struct {
    Total int    `json:"total"`
    Items []Task `json:"items"`
}

// 定义Task结构体
type Task struct {
    ID          int    `json:"id"`
    Title       string `json:"title"`
    Description string `json:"description"`
    Completed   bool   `json:"completed"`
}

// 添加用户相关结构体
type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Password string `json:"-"` // 不返回密码
}

type LoginRequest struct {
    Username string `json:"username"`
    Password string `json:"password"`
}

func initDB(db *sql.DB) error {
    // 先删除现有的表（注意顺序：先删除有外键约束的表）
    _, err := db.Exec(`DROP TABLE IF EXISTS tasks`)
    if err != nil {
        return err
    }
    
    _, err = db.Exec(`DROP TABLE IF EXISTS users`)
    if err != nil {
        return err
    }

    // 创建 users 表
    _, err = db.Exec(`
        CREATE TABLE IF NOT EXISTS users (
            id INT AUTO_INCREMENT PRIMARY KEY,
            username VARCHAR(255) NOT NULL UNIQUE,
            password VARCHAR(255) NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    `)
    if err != nil {
        return err
    }

    // 创建 tasks 表
    _, err = db.Exec(`
        CREATE TABLE IF NOT EXISTS tasks (
            id INT AUTO_INCREMENT PRIMARY KEY,
            title VARCHAR(255) NOT NULL,
            description TEXT,
            completed BOOLEAN DEFAULT FALSE,
            user_id INT NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            FOREIGN KEY (user_id) REFERENCES users(id)
        )
    `)
    return err
}

func main() {
        // 连接到MySQL数据库
        config := config.GetConfig()
        dataSourceName := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", 
            config.DBUser, config.DBPassword, config.DBHost, config.DBPort, config.DBName)
        
        log.Printf("Connecting to database: %s (password hidden)", 
            fmt.Sprintf("%s:***@tcp(%s:%s)/%s", 
                config.DBUser, config.DBHost, config.DBPort, config.DBName))

        db, err := sql.Open("mysql", dataSourceName)
        if err != nil {
            log.Fatal("Error connecting to database:", err)
        }
        defer db.Close()

        // 初始化数据库
        if err := initDB(db); err != nil {
            log.Fatal("Error initializing database:", err)
        }

        // 测试连接
        err = db.Ping()
        if err != nil {
            log.Fatal("Error pinging database:", err)
        }

        log.Printf("Starting server on http://localhost:8080")

        http.HandleFunc("/register", func(w http.ResponseWriter, r *http.Request) {
            registerHandler(w, r, db)
        })
        
        http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
            loginHandler(w, r, db)
        })

        http.HandleFunc("/tasks", func(w http.ResponseWriter, r *http.Request) {
            // 验证token
            userID, err := validateToken(r)
            if err != nil {
                http.Error(w, "Unauthorized", http.StatusUnauthorized)
                return
            }

            switch r.Method {
            case "GET":
                getTasks(w, r, db, userID)
            case "POST":
                if r.URL.Query().Get("action") == "update_status" {
                    updateTaskStatus(w, r, db, userID)
                } else {
                    createTask(w, r, db, userID)
                }
            case "DELETE":
                deleteTask(w, r, db, userID)
            default:
                http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
            }
        })

        log.Fatal(http.ListenAndServe(":8080", nil))
}

func getTasks(w http.ResponseWriter, r *http.Request, db *sql.DB, userID int) {
    log.Printf("Getting tasks for user ID: %d", userID)
    
    // 获取分页参数
    page := r.URL.Query().Get("page")
    pageSize := r.URL.Query().Get("pageSize")
    search := r.URL.Query().Get("search")
    
    if page == "" {
        page = "1"
    }
    if pageSize == "" {
        pageSize = "10"
    }
    
    pageNum, _ := strconv.Atoi(page)
    size, _ := strconv.Atoi(pageSize)
    offset := (pageNum - 1) * size

    // 构建查询条件
    whereClause := "WHERE user_id = ?"
    params := []interface{}{userID}
    if search != "" {
        whereClause += " AND (title LIKE ? OR description LIKE ?)"
        params = append(params, "%"+search+"%", "%"+search+"%")
    }

    // 获取总数
    countQuery := "SELECT COUNT(*) FROM tasks " + whereClause
    log.Printf("Count query: %s, params: %v", countQuery, params)
    
    var total int
    if err := db.QueryRow(countQuery, params...).Scan(&total); err != nil {
        log.Printf("Error getting count: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    log.Printf("Total records: %d", total)

    // 获取分页数据
    query := "SELECT id, title, description, completed FROM tasks " + whereClause + " LIMIT ? OFFSET ?"
    log.Printf("Data query: %s, params: %v", query, append(params, size, offset))
    
    params = append(params, size, offset)
    rows, err := db.Query(query, params...)
    if err != nil {
        log.Printf("Error querying tasks: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer rows.Close()

    var tasks []Task
    for rows.Next() {
        var t Task
        if err := rows.Scan(&t.ID, &t.Title, &t.Description, &t.Completed); err != nil {
            log.Printf("Error scanning row: %v", err)
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        tasks = append(tasks, t)
    }

    // 返回分页响应
    response := PaginatedResponse{
        Total: total,
        Items: tasks,
    }

    w.Header().Set("Content-Type", "application/json")
    if err := json.NewEncoder(w).Encode(response); err != nil {
        log.Printf("Error encoding response: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

func createTask(w http.ResponseWriter, r *http.Request, db *sql.DB, userID int) {
    log.Printf("Creating task for user ID: %d", userID)

    var task struct {
        Title       string `json:"title"`
        Description string `json:"description"`
        Completed   bool   `json:"completed"`
    }
    if err := json.NewDecoder(r.Body).Decode(&task); err != nil {
        log.Printf("Error decoding request: %v", err)
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    // 检查标题是否已存在
    var exists bool
    err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM tasks WHERE title = ? AND user_id = ?)", 
        task.Title, userID).Scan(&exists)
    if err != nil {
        log.Printf("Error checking title existence: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    if exists {
        log.Printf("Task with title '%s' already exists for user %d", task.Title, userID)
        http.Error(w, "Task with this title already exists", http.StatusConflict)
        return
    }

    result, err := db.Exec(
        "INSERT INTO tasks (title, description, completed, user_id) VALUES (?, ?, ?, ?)", 
        task.Title, 
        task.Description,
        task.Completed,
        userID,
    )
    if err != nil {
        log.Printf("Error inserting task: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    id, err := result.LastInsertId()
    if err != nil {
        log.Printf("Error getting last insert ID: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    response := map[string]interface{}{
        "id":          id,
        "title":       task.Title,
        "description": task.Description,
        "completed":   task.Completed,
        "user_id":     userID,
    }
    
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)  // 设置 201 状态码表示创建成功
    if err := json.NewEncoder(w).Encode(response); err != nil {
        log.Printf("Error encoding response: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

func deleteTask(w http.ResponseWriter, r *http.Request, db *sql.DB, userID int) {
        var task struct {
                ID int `json:"id"`
        }
        if err := json.NewDecoder(r.Body).Decode(&task); err != nil {
                http.Error(w, err.Error(), http.StatusBadRequest)
                return
        }

        // 确保只能删除自己的任务
        result, err := db.Exec("DELETE FROM tasks WHERE id = ? AND user_id = ?", task.ID, userID)
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
        }

        affected, err := result.RowsAffected()
        if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
                return
        }
        if affected == 0 {
                http.Error(w, "Task not found or not authorized", http.StatusNotFound)
                return
        }

        fmt.Fprintf(w, `{"message": "Task deleted successfully"}`)
}

func registerHandler(w http.ResponseWriter, r *http.Request, db *sql.DB) {
    log.Printf("Received register request") // 添加日志

    if r.Method != "POST" {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }

    var req struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }

    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        log.Printf("Error decoding request: %v", err)
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    log.Printf("Registering user: %s", req.Username)

    // 检查用户名是否已存在
    var exists bool
    err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM users WHERE username = ?)", req.Username).Scan(&exists)
    if err != nil {
        log.Printf("Error checking username existence: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    if exists {
        log.Printf("Username already exists: %s", req.Username)
        http.Error(w, "Username already exists", http.StatusConflict)
        return
    }

    // 插入新用户
    result, err := db.Exec(
        "INSERT INTO users (username, password) VALUES (?, ?)",
        req.Username,
        req.Password,
    )
    if err != nil {
        log.Printf("Error inserting user: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    userID, err := result.LastInsertId()
    if err != nil {
        log.Printf("Error getting last insert ID: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    log.Printf("User registered successfully - ID: %d, Username: %s", userID, req.Username)

    // 返回成功响应
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(map[string]interface{}{
        "id":       userID,
        "username": req.Username,
    })
}

func loginHandler(w http.ResponseWriter, r *http.Request, db *sql.DB) {
    log.Printf("Received login request") // 添加日志

    if r.Method != "POST" {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }

    var req struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }

    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        log.Printf("Error decoding request: %v", err)
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    log.Printf("Login attempt for user: %s", req.Username) // 添加日志

    var user struct {
        ID       int    `json:"id"`
        Username string `json:"username"`
    }

    // 查询用户
    err := db.QueryRow("SELECT id, username FROM users WHERE username = ? AND password = ?",
        req.Username, req.Password).Scan(&user.ID, &user.Username)
    
    if err == sql.ErrNoRows {
        log.Printf("Invalid credentials for user: %s", req.Username)
        http.Error(w, "Invalid credentials", http.StatusUnauthorized)
        return
    }
    if err != nil {
        log.Printf("Database error: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // 生成JWT token
    token, err := auth.GenerateToken(user.ID)
    if err != nil {
        log.Printf("Error generating token: %v", err)
        http.Error(w, "Error generating token", http.StatusInternalServerError)
        return
    }

    log.Printf("User logged in successfully - ID: %d, Username: %s", user.ID, user.Username)

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]interface{}{
        "token": token,
        "user":  user,
    })
}

func validateToken(r *http.Request) (int, error) {
    authHeader := r.Header.Get("Authorization")
    if authHeader == "" {
        return 0, fmt.Errorf("no token provided")
    }

    // Bearer token格式
    parts := strings.Split(authHeader, " ")
    if len(parts) != 2 || parts[0] != "Bearer" {
        return 0, fmt.Errorf("invalid token format")
    }

    return auth.ValidateToken(parts[1])
}

func updateTaskStatus(w http.ResponseWriter, r *http.Request, db *sql.DB, userID int) {
    log.Printf("Updating task status for user ID: %d", userID)

    var request struct {
        ID        int  `json:"id"`
        Completed bool `json:"completed"`
    }
    if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
        log.Printf("Error decoding request: %v", err)
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    // 更新任务状态，确保只能更新自己的任务
    result, err := db.Exec(
        "UPDATE tasks SET completed = ? WHERE id = ? AND user_id = ?",
        request.Completed,
        request.ID,
        userID,
    )
    if err != nil {
        log.Printf("Error updating task: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    affected, err := result.RowsAffected()
    if err != nil {
        log.Printf("Error getting affected rows: %v", err)
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    if affected == 0 {
        log.Printf("Task not found or not authorized - Task ID: %d, User ID: %d", request.ID, userID)
        http.Error(w, "Task not found or not authorized", http.StatusNotFound)
        return
    }

    log.Printf("Task status updated successfully - Task ID: %d, User ID: %d", request.ID, userID)
    w.WriteHeader(http.StatusOK)
}
